import configparser
import datetime
import json
import os
import re
import time
import qrcode
from PIL import Image
import requests
import random
import json

from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from seleniumwire import webdriver


# 获取脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
# 构建配置文件的完整路径
config_path = os.path.join(script_dir, 'config')
driver_path = os.path.join(script_dir, 'drivers')
icon_path = os.path.join(script_dir, '临时图标')

def read_config(file_path=os.path.join(config_path, 'config.ini')):
    """读取配置文件并返回配置解析器"""
    config = configparser.ConfigParser()
    config.read(file_path)
    return config


def browser_init(url, type='browser'):
    """
    初始化Selenium WebDriver，完全依赖配置文件中的路径信息。

    :param url: 访问的网址
    :param config_file: 配置文件路径，默认为'config.ini'
    :return: 初始化后的WebDriver实例
    """

    if type == 'mobile':
        # 自定义User-Agent字符串以接近小米设备，这里以一个示例User-Agent为例，实际可能需要根据小米14的具体版本调整
        user_agent = "Mozilla/5.0 (Linux; Android 11; M2012K11AC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.101 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.3.4"

        # 设置Chrome模拟选项
        chrome_options = Options()

        # 模拟User-Agent
        chrome_options.add_argument(f"user-agent={user_agent}")

        # 设置窗口大小，这里以小米14的屏幕分辨率作为参考，小米14的分辨率为FHD+，常见为1080x2400
        chrome_options.add_argument("--window-size=1080,2400")

        # 启用移动设备模拟，虽然不直接指定小米14，但可以通过上述User-Agent和窗口大小近似模拟
        chrome_options.add_argument('--disable-blink-features=AutomationControlled')  # 可选，用来规避一些网站对自动化浏览器的检测

        # 初始化WebDriver
        driver = webdriver.Chrome(options=chrome_options)
    else:
        config = read_config()
        paths = config['Paths']

        current_path = os.path.dirname(os.path.abspath(__file__))
        print(current_path)

        # 初始化Selenium Wire驱动
        options = Options()
        # 阻止浏览器在退出时关闭
        options.add_experimental_option("detach", True)
        # 添加参数以排除显示“Chrome 正受到自动测试软件的控制”的提示
        options.add_experimental_option("excludeSwitches", ["enable-automation"])

        # 使用配置文件中的路径
        user_data_dir = paths.get('user_data_dir')
        if user_data_dir:
            options.add_argument(f"user-data-dir={user_data_dir}")

        chrome_binary = paths.get('chrome_binary')
        if chrome_binary:
            options.binary_location = chrome_binary

        # 使用配置文件中的ChromeDriver路径
        chromedriver_path = paths.get('chromedriver_path')
        if chromedriver_path:
            # raise FileNotFoundError("Chromedriver path not specified in the config file.")
            service = Service(chromedriver_path)
        else:
            service = Service(os.path.join(driver_path, "chromedriver.exe"))

        # options.add_argument(r"user-data-dir=C:\Users\14421\AppData\Local\Google\Chrome\User Data")
        # options.binary_location = r"C:\Program Files\Google\Chrome\Application\chrome.exe"

        options.add_argument("--start-maximized")  # 开始最大化
        options.add_argument("--test-type")
        options.add_argument("--ignore-certificate-errors")  # 忽略证书错误

        options.add_argument("--disable-popup-blocking")  # 禁用弹出拦截
        options.add_argument("no-sandbox")  # 取消沙盒模式
        options.add_argument("no-default-browser-check")  # 禁止默认浏览器检查
        options.add_argument("about:histograms")
        options.add_argument("about:cache")

        # options.add_argument("disable-extensions")  # 禁用扩展
        options.add_argument("disable-glsl-translator")  # 禁用GLSL翻译

        options.add_argument("disable-translate")  # 禁用翻译
        options.add_argument("--disable-gpu")  # 谷歌文档提到需要加上这个属性来规避bug
        options.add_argument("--disable-dev-shm-usage")
        options.add_argument("--hide-scrollbars")  # 隐藏滚动条, 应对一些特殊页面
        # options.add_argument("blink-settings=imagesEnabled=false")  # 不加载图片, 提升速度

        driver = webdriver.Chrome(options=options, service=service, keep_alive=True)
    driver.maximize_window()
    time.sleep(3)
    driver.get(url)
    time.sleep(3)

    return driver


def get_selenium_cookies(driver):
    """从Selenium中提取Cookies"""
    selenium_cookies = driver.get_cookies()
    cookies = {c['name']: c['value'] for c in selenium_cookies}
    return cookies


def reissue_request_with_cookies(url, cookies, headers, method, data=None):
    """使用requests重新发起请求并携带Cookies"""
    # headers = {
    #     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36'}
    if method == 'get':
        response = requests.get(url, cookies=cookies, headers=headers)
    else:
        response = requests.post(url, cookies=cookies, headers=headers, data=data)
    return response


def get_video_count(driver, name):
    try:
        url = f'https://www.ixigua.com/search/{name}/?tab_name=search&fss=input&typeIndex=2'
        # driver = browser_init(url)
        driver.get(url)
        time.sleep(3)
        video_count = driver.find_element(By.XPATH,
                                          '//*[@id="App"]/div/main/div/div/div[3]/div/div[1]/div/div[1]/div/div[2]/a').text
        # driver.quit()
        video_count = re.findall(r'· (\d+)个视频', video_count)[0]
    except Exception:
        video_count = '自定义'
    print(video_count)
    return video_count


def get_data(url):
    # 目标网站URL
    feed_api_prefix = "https://www.toutiao.com/api/pc/list/user/feed?category=profile_all"  # 目标API前缀
    fans_api_prefix = 'https://www.toutiao.com/api/pc/user/fans_stat'  # 目标API前缀

    # 初始化Selenium Wire驱动
    driver = browser_init(url)

    # 筛选并尝试直接从Selenium Wire获取响应
    matched_req = [req for req in driver.requests if req.url.startswith(feed_api_prefix)][0]
    print(matched_req)
    dig_req = [req for req in driver.requests if req.url.startswith(fans_api_prefix)][0]
    print(dig_req)

    # 使用requests重新发起请求
    cookies = get_selenium_cookies(driver)
    response = reissue_request_with_cookies(matched_req, cookies, matched_req.headers, 'get')
    # print(response.status_code)
    # print(response.encoding)
    # print(f"使用requests重新请求的响应: {response.json()}")
    data = response.json()['data']
    token = data[0]['user']['user_id']
    # FormData部分
    form_data = {
        'token': token,
        # 注意如果有多个FormData参数，继续在此字典中添加
    }
    # 把总的点赞数加到数据中
    response = reissue_request_with_cookies(dig_req, cookies, dig_req.headers, 'post', form_data)
    print(response.json())
    dig_count = response.json()['data']['digg_count']
    # 给第一个视频多添加一个总的点赞数
    data[0]['dig_count'] = init_dig_counts(dig_count)
    # 给第一个视频多添加一个总的作品数
    name = data[0]['user']['info']['name']
    data[0]['video_count'] = get_video_count(driver, name)

    # 清理
    driver.quit()
    # print(data)
    return data


def get_dig_count():
    # 目标网站URL
    target_api_prefix = 'https://www.toutiao.com/api/pc/user/fans_stat'  # 目标API前缀


def format_duration(seconds):
    # 计算小时、分钟和秒数
    hours = seconds // 3600
    remaining_seconds = seconds % 3600
    minutes = remaining_seconds // 60
    seconds = remaining_seconds % 60

    # 格式化为时:分:秒的形式
    if hours > 0:
        return f'{hours:02}:{minutes:02}:{seconds:02}'
    else:
        return f'{minutes:02}:{seconds:02}'


def unix_to_beijing_time(unix_timestamp):
    # 将 UNIX 时间戳转换为本地时间
    local_time = time.localtime(unix_timestamp)
    # 将本地时间转换为北京时间
    beijing_time = datetime.datetime.fromtimestamp(unix_timestamp) + datetime.timedelta()

    # 获取当前日期的年份
    current_year = datetime.datetime.now().year

    # 如果时间戳对应的年份是当前年份，则只显示月日时分
    if beijing_time.year == current_year:
        return beijing_time.strftime('%m-%d %H:%M')
    else:
        return beijing_time.strftime('%Y-%m-%d %H:%M')


def make_qrcode(url, user_id):
    # 生成二维码
    qr = qrcode.QRCode(
        version=3,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=8.5,
        border=1,  # 添加一个单位的边框宽度
    )
    qr.add_data(f'http://toutiao.com/c/user/{user_id}/?from=qrcode')
    qr.make(fit=True)
    img_qr = qr.make_image(fill_color="black", back_color="white")

    # 下载头像图片
    response = requests.get(url)
    avatar_img = Image.open(BytesIO(response.content))

    # 计算头像的大小
    avatar_size = (img_qr.size[0] // 5, img_qr.size[1] // 5)

    # 调整头像大小并保持原始颜色
    avatar_img = avatar_img.resize(avatar_size).convert("RGBA")
    img_qr = img_qr.convert("RGBA")

    # 计算头像放置位置
    avatar_pos = ((img_qr.size[0] - avatar_size[0]) // 2, (img_qr.size[1] - avatar_size[1]) // 2)

    # 将头像粘贴到二维码上
    img_qr.paste(avatar_img, avatar_pos, avatar_img)

    qrcode_path = os.path.join(icon_path, 'qrcode.png')
    if not os.path.exists(icon_path):
        os.makedirs(icon_path)
    # 保存结果
    img_qr.save(qrcode_path)
    return qrcode_path


def make_name():
    surnames = ['王', '李', '张', '刘', '陈', '杨', '赵', '黄', '周', '吴', '徐', '孙', '胡', '朱', '高', '林', '何',
                '郭', '马', '罗']
    name = f'{random.choice(surnames)}**(1*****{random.randint(1, 9)})'
    return name


import base64
from io import BytesIO


def image_to_base64(image_path):
    """
    将图片文件转换为Base64编码字符串
    :param image_path: 图片文件的路径
    :return: Base64编码的字符串
    """
    with open(image_path, "rb") as image_file:
        encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
    return "data:image/png;base64," + encoded_string


def generate_formatted_phone_number():
    """生成脱敏的随机手机号，例如：173******04"""
    # 第一位固定为1
    first_digit = '1'
    # 第二位数字可以是3、4、5、6、7、8、9中的任意一个
    second_digit_options = ['3', '4', '5', '6', '7', '8', '9']
    second_digit = random.choice(second_digit_options)
    # 随机生成后八位数字
    remaining_digits = ''.join(str(random.randint(0, 9)) for _ in range(8))
    # 完整的随机手机号
    full_phone_number = first_digit + second_digit + remaining_digits

    # 格式化显示：前三位 + **** + 后4位
    formatted_phone_number = f"{full_phone_number[:3]}{'*' * 4}{full_phone_number[-4:]}"
    return formatted_phone_number

def init_dig_counts(dig_count):
    """格式化总的点赞数，原数据会带万单位"""
    if isinstance(dig_count, int):
        return dig_count
    if '万' in dig_count:
        if '.' in dig_count:
            dig_count = float(dig_count.replace('万', '').replace(',', ''))*10000
        else:
            dig_count = int(dig_count.replace('万', '').replace(',', ''))*10000
    else:
        dig_count = int(dig_count.replace(',', ''))
    return int(dig_count)


def init_read_counts(read_count):
    """格式化总阅读数，返回900万、亿单位"""
    if read_count >= 100000000:
        read_count = float(read_count/100000000)
        read_count = f'{round(read_count, 1)}亿'
    elif read_count >= 1000000:
        read_count = float(read_count/10000)
        read_count = f'{round(read_count, 1)}万'
    else:
        read_count = f'{read_count:,}'
    return read_count


def make_read_count(dig_count):
    """根据点赞数计算阅读数"""
    dig_count = int(dig_count)
    n = random.randint(220, 230)

    read_count = dig_count * n
    return read_count


def make_income_count(read_count):
    """根据阅读数数计算收益"""
    read_count = read_count
    n = random.uniform(4, 6)
    income_count = read_count / 10000 * n

    return f"{income_count:,.2f}"


import random
import pycountry


def transform_address(address):
    try:
        # 解析地址字符串
        province = address.split("来自")[1]

        # 获取对应省份的行政区划信息
        province_info = pycountry.subdivisions.lookup(f"CN-{province}")

        if province_info:
            # 如果是直辖市，则只显示城市
            if province_info.type == "municipality":
                return f"中国大陆/{province_info.name}/"
            else:
                # 随机选择一个城市
                city = random.choice(province_info.subdivisions)
                return f"中国大陆/{province_info.name}/{city.name}"
        else:
            return None  # 如果省份不在数据中，则返回 None
    except IndexError:
        return None  # 如果解析地址时发生索引错误，则返回 None


# def init_data(data):
#     """按照指定格式初始化数据"""
#     info = {}  # 当前对标账号的所有信息
#     # 用户信息从任意一个作品中提取
#     info['昵称'] = data[0]['user']['info']['name']
#     info['头像'] = data[0]['user']['info']['avatar_url']
#     info['头条号id'] = data[0]['user']['info']['media_id']  # 设置页需要
#     info['用户id'] = str(data[0]['user']['info']['user_id'])  # 设置页二维码需要
#     info['用户二维码'] = image_to_base64(make_qrcode(info['头像'], info['用户id']))  # 这里要转成base64
#     info['用户简介'] = data[0]['user']['info']['desc']
#     info['联系方式'] = generate_formatted_phone_number()  # 随机
#     address = json.loads(data[0]['itemCell']['shortVideoCustom']['diversityData'])['publish_loc_info'].replace('来自', '')
#     info['注册地址'] = f'中国大陆/{address}'  # 自定义
#     info['运营人'] = make_name()  # 随机，姓氏随便取一个，田**(1*****7)
#
#     info['消息数量'] = str(random.randint(1, 10))  # 随机取1-10
#     info['创作天数'] = f'在头条创作的第 {100} 天'  # 这个得从最早的发布时间算起，在头条创作的第 2047 天
#     info['粉丝数'] = format_count(data[0]['user']['relation_count']['followers_count'])
#     read_count = make_read_count(data[0]['dig_count'])
#     info['总阅读'] = init_read_counts(read_count)
#     info['总收益'] = make_income_count(read_count)
#     info['昨日粉丝增加量'] = random.randint(10, 100)  # 固定列表随机
#     info['昨日阅读增加量'] = random.randint(10000, 100000)  # 固定列表随机
#     info['昨日收益增加量'] = round(random.uniform(10.01, 100.01), 2)  # 固定列表随机
#     info['内容篇数'] = f"共 {data[0]['video_count']} 条内容"  # 总作品数，可以在西瓜视频查询到，共 45 条内容
#
#     # 下面就是作品--约定至少6条，需要数量也为6条
#     for i in range(10):
#         info[f'标题{i + 1:02}'] = data[i]['title']
#         info[f'封面{i + 1:02}'] = data[i]['video_detail_info']['detail_video_large_image']['url']
#         info[f'时长{i + 1:02}'] = format_duration(data[i]['video']['duration'])
#         info[f'时间{i + 1:02}'] = unix_to_beijing_time(data[i]['publish_time'])
#         info[f'展现{i + 1:02}'] = format_count(data[i]['itemCell']['itemCounter']['showCount'])
#         info[f'播放{i + 1:02}'] = format_count(data[i]['itemCell']['itemCounter']['readCount'])
#         info[f'评论{i + 1:02}'] = format_count(data[i]['itemCell']['itemCounter']['commentCount'])
#         info[f'点赞{i + 1:02}'] = format_count(data[i]['itemCell']['itemCounter']['diggCount'])
#     print(info)
#     return info




def init_data(data):
    """按照指定格式初始化数据"""
    info = {}  # 当前对标账号的所有信息

    try:
        info['昵称'] = data[0]['user']['info']['name']
    except KeyError:
        info['昵称'] = '自定义'

    try:
        info['头像'] = data[0]['user']['info']['avatar_url']
    except KeyError:
        info['头像'] = '自定义'

    try:
        info['头条号id'] = data[0]['user']['info']['media_id']
    except KeyError:
        info['头条号id'] = '自定义'

    try:
        info['用户id'] = str(data[0]['user']['info']['user_id'])
        info['用户二维码'] = image_to_base64(make_qrcode(info['头像'], info['用户id']))
    except KeyError:
        info['用户id'] = '自定义'
        info['用户二维码'] = '自定义'

    try:
        info['用户简介'] = data[0]['user']['info']['desc']
    except KeyError:
        info['用户简介'] = '自定义'

    info['联系方式'] = generate_formatted_phone_number()  # 随机生成

    try:
        address = json.loads(data[0]['itemCell']['shortVideoCustom']['diversityData'])['publish_loc_info'].replace(
            '来自', '')
        info['注册地址'] = f'中国大陆/{address}'
    except (KeyError, json.JSONDecodeError):
        info['注册地址'] = '中国大陆/自定义'

    info['运营人'] = make_name()  # 随机生成

    info['消息数量'] = str(random.randint(1, 10))  # 随机取1-10

    info['创作天数'] = f'在头条创作的第 {100} 天'  # 自定义

    try:
        info['粉丝数'] = format_count(data[0]['user']['relation_count']['followers_count'])
    except KeyError:
        info['粉丝数'] = '自定义'

    try:
        read_count = make_read_count(data[0]['dig_count'])
        info['总阅读'] = init_read_counts(read_count)
        info['总收益'] = make_income_count(read_count)
    except KeyError:
        info['总阅读'] = '自定义'
        info['总收益'] = '自定义'

    info['昨日粉丝增加量'] = random.randint(10, 100)  # 固定列表随机

    info['昨日阅读增加量'] = random.randint(10000, 100000)  # 固定列表随机

    info['昨日收益增加量'] = round(random.uniform(10.01, 100.01), 2)  # 固定列表随机
    try:
        info['内容篇数'] = f"共 {data[0]['video_count']} 条内容"  # 总作品数，可以在西瓜视频查询到，共 45 条内容
    except Exception:
        info['内容篇数'] = '自定义'
    # 下面就是作品--约定至少10条，需要数量也为10条
    for i in range(10):
        try:
            info[f'标题{i + 1:02}'] = data[i]['title']
        except KeyError:
            info[f'标题{i + 1:02}'] = '自定义'

        try:
            info[f'封面{i + 1:02}'] = data[i]['video_detail_info']['detail_video_large_image']['url']
        except KeyError:
            info[f'封面{i + 1:02}'] = '自定义'

        try:
            info[f'时长{i + 1:02}'] = format_duration(data[i]['video']['duration'])
        except KeyError:
            info[f'时长{i + 1:02}'] = '自定义'

        try:
            info[f'时间{i + 1:02}'] = unix_to_beijing_time(data[i]['publish_time'])
        except KeyError:
            info[f'时间{i + 1:02}'] = '自定义'

        try:
            info[f'展现{i + 1:02}'] = format_count(data[i]['itemCell']['itemCounter']['showCount'])
        except KeyError:
            info[f'展现{i + 1:02}'] = '自定义'

        try:
            info[f'播放{i + 1:02}'] = format_count(data[i]['itemCell']['itemCounter']['readCount'])
        except KeyError:
            info[f'播放{i + 1:02}'] = '自定义'

        try:
            info[f'评论{i + 1:02}'] = format_count(data[i]['itemCell']['itemCounter']['commentCount'])
        except KeyError:
            info[f'评论{i + 1:02}'] = '自定义'

        try:
            info[f'点赞{i + 1:02}'] = format_count(data[i]['itemCell']['itemCounter']['diggCount'])
        except KeyError:
            info[f'点赞{i + 1:02}'] = '自定义'

    print(info)
    return info


def format_count(count):
    """数字中每三个数字添加一个逗号作为千位分隔符"""
    return f'{count:,}'

if __name__ == "__main__":
    url = 'https://www.toutiao.com/c/user/token/MS4wLjABAAAApDB1NKvDOmXYuozBzyi9ZsIoD9d0NalfBTCFe-eMI4JpBQgSzIOa9sj5_DfcN_gI/?source=m_redirect'
    data = get_data(url)
    data = init_data(data)
    print(data)
    config = read_config()
    print(config['Paths']['user_data_dir'])
    time.sleep(1000)

    # video_count = '粉丝：22万 · 145个视频'
    # video_count = re.findall(r'· (\d+)个视频', video_count)[0]
    # print(video_count)
    # user_id = '109691944292'
    # avatar_url = 'https://p3-sign.toutiaoimg.com/user-avatar/1c361e81b4e6eab8be4325cd8bac0bf4~300x300.image?_iz=112761&from=tt_user.profile_all_shortvideo&lk3s=06827d14&x-expires=1718668800&x-signature=ccvitfluSytEivakgszeh9p%2BoOc%3D'
    # make_qrcode(avatar_url, user_id)
    # pass

# def login():
#     drivers.get('https://mp.toutiao.com/profile_v4/index')
#     time.sleep(5)
#
#     with open('account.json', 'r', encoding='utf-8') as f:
#         config = json.load(f)
#     username = config['account']['username']
#     password = config['account']['password']
#
#     drivers.find_element(By.XPATH, '//*[@id="BD_Login_Form"]/div/article/article/div[2]/div/ul/li[4]/i').click()
#     time.sleep(2)
#     drivers.find_element(By.XPATH, '//*[@id="BD_Login_Form"]/div/article/article/div[1]/div[1]/div[2]/article/div[1]/div/input').send_keys(username)
#     time.sleep(3)
#     drivers.find_element(By.XPATH, '//*[@id="BD_Login_Form"]/div/article/article/div[1]/div[1]/div[2]/article/div[2]/div/div/input').send_keys(password)
#     time.sleep(2)
#     drivers.find_element(By.XPATH, '//*[@id="BD_Login_Form"]/div/article/article/div[1]/div[1]/div[2]/article/div[4]/span[1]').click()
#     time.sleep(2)
#     drivers.find_element(By.XPATH, '//*[@id="BD_Login_Form"]/div/article/article/div[1]/div[1]/div[2]/article/div[5]/button').click()
#     time.sleep(10)
